package com.ecoolex.ying.space.core.manager;

import com.alibaba.fastjson.JSON;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.ying.space.core.dao.DesignerProjectItemsDAO;
import com.ecoolex.ying.space.entity.DesignerProject;
import com.ecoolex.ying.space.entity.DesignerProjectItems;
import com.ecoolex.ying.space.entity.DesignerProjectItemsExample;
import com.ecoolex.ying.space.entity.DesignerProjectItemsWithBLOBs;
import com.ecoolex.ying.space.entity.DesignerProjectItemsWithBLOBs.Column;
import com.ecoolex.ying.space.pojo.DesignerProjectListingItemsDTO;
import com.ecoolex.ying.space.pojo.DesignerProjectPlanItemsDTO;
import com.ecoolex.ying.space.pojo.EditDesignerProjectListingItemsDTO;
import com.ecoolex.ying.space.pojo.EditDesignerProjectPlanItemsDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.event.ItemEvent;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.ecoolex.ying.space.entity.DesignerProjectItems.*;

@Service
public class DesignerProjectItemsManager {
    @Autowired
    private DesignerProjectItemsDAO dao;

    @Autowired
    private DesignerProjectItemsProductManager designerProjectItemsProductManager;
    @Autowired
    private DesignerProjectItemsProductCustomManager designerProjectItemsProductCustomManager;

    private void verifyPlan(List<EditDesignerProjectPlanItemsDTO> editList) {
        BizAssert.isTrue(Check.notNull(editList), ResultCode.VERIFY.build(40), "条目集合不能为空");
        editList.forEach(item -> {
            BizAssert.isTrue(Check.notNull(item), ResultCode.VERIFY.build(41), "条目不能为空");
            BizAssert.isTrue(Check.notNull(item.getChangeType()), ResultCode.VERIFY.build(42), "变更类型不能为空");
            if (item.getChangeType() == 2) {
                BizAssert.isTrue(Check.notNull(item.getItemsId()), ResultCode.VERIFY.build(43), "删除时ItemsId不能为空");
            } else if (item.getChangeType() == 1) {
                BizAssert.isTrue(Check.notNullOrTrimEmpty(item.getName()), ResultCode.VERIFY.build(44), "条目名称不能为空");
            }
        });
        // 重复检查
        List filter = editList.stream()
                .filter(item -> Check.notNull(item.getItemsId()))
                .map(EditDesignerProjectPlanItemsDTO::getItemsId)
                .collect(Collectors.toList());
        BizAssert.isTrue(filter.size() == filter.stream().distinct().count(), ResultCode.VERIFY.build(45), "ItemsId存在重复数据");
    }

    @Transactional
    public List<DesignerProjectPlanItemsDTO> updatePlanItems(DesignerProject project, List<EditDesignerProjectPlanItemsDTO> editList, String updateUser) {
        // 检查参数
        verifyPlan(editList);
        IntStream.range(0, editList.size()).forEachOrdered(i -> {
            EditDesignerProjectPlanItemsDTO edit = editList.get(i);
            if (edit.getChangeType() == 1) {
                if (Check.isNull(edit.getItemsId())) {
                    // 添加
                    DesignerProjectItems items = create(project, edit, i, updateUser);
                    edit.setItemsId(items.getItemsId());
                } else {
                    // 修改
                    update(project, edit, i, updateUser);
                }
                // 变更内容
                designerProjectItemsProductManager.update(project, edit.getItemsId(), edit.getPickProducts(), updateUser);
            } else if (edit.getChangeType() == 2 && Check.notNull(edit.getItemsId())) {
                delete(project, edit.getItemsId(), updateUser);
                // 删除产品
                designerProjectItemsProductManager.deleteByItemsId(project, edit.getItemsId(), updateUser);
                // 删除自定义数据
                designerProjectItemsProductCustomManager.deleteByItemsId(project, edit.getItemsId(), updateUser);
                edit.setItemsId(null);
            }
        });
        return editList.stream().filter(item -> Check.notNull(item.getItemsId())).collect(Collectors.toList());
    }

    void copy(Integer sourceProjectId, DesignerProject project, String createUser) {
        queryByProjectId(sourceProjectId).forEach(item -> {
            Integer sourceItemId = item.getItemsId();

            item.setProjectId(project.getProjectId());
            item.setCreateUser(createUser);
            item.setCreateTime(Date.from(Instant.now()));
            item.setUpdateUser(createUser);
            item.setUpdateTime(Date.from(Instant.now()));
            dao.insert(item);

            designerProjectItemsProductManager.copy(sourceItemId, item, createUser);
        });
    }

    private DesignerProjectItems create(DesignerProject project, EditDesignerProjectPlanItemsDTO edit, int sorting, String createUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setUserId(project.getUserId());
        record.setProjectId(project.getProjectId());
        record.setName(edit.getName());
        record.setContent(edit.getContent());
        record.setPositionDescr(edit.getPositionDescr());
        record.setImageResources(Check.isNull(edit.getImages()) ? null : JSON.toJSONString(edit.getImages()));
        record.setSorting(sorting);
        record.setDeleted(NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);
        return record;
    }

    private void update(DesignerProject project, EditDesignerProjectPlanItemsDTO edit, int sorting, String updateUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setName(edit.getName());
        record.setContent(edit.getContent());
        record.setPositionDescr(edit.getPositionDescr());
        record.setImageResources(Check.isNull(edit.getImages()) ? null : JSON.toJSONString(edit.getImages()));
        record.setSorting(sorting);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        DesignerProjectItemsExample example = new DesignerProjectItemsExample();
        example.createCriteria()
                .andItemsIdEqualTo(edit.getItemsId())
                .andProjectIdEqualTo(project.getProjectId())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.name,
                Column.content,
                Column.positionDescr,
                Column.imageResources,
                Column.sorting,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(40), "修改条目失败");
    }

    private void verifyListing(List<EditDesignerProjectListingItemsDTO> editList) {
        BizAssert.isTrue(Check.notNull(editList), ResultCode.VERIFY.build(40), "条目集合不能为空");
        editList.forEach(item -> {
            BizAssert.isTrue(Check.notNull(item), ResultCode.VERIFY.build(41), "条目不能为空");
            BizAssert.isTrue(Check.notNull(item.getChangeType()), ResultCode.VERIFY.build(42), "变更类型不能为空");
            if (item.getChangeType() == 2) {
                BizAssert.isTrue(Check.notNull(item.getItemsId()), ResultCode.VERIFY.build(43), "删除时ItemsId不能为空");
            } else if (item.getChangeType() == 1) {
                BizAssert.isTrue(Check.notNullOrTrimEmpty(item.getPositionDescr()), ResultCode.VERIFY.build(44), "条目位置不能为空");
            }
        });
        // 重复检查
        List filter = editList.stream()
                .filter(item -> Check.notNull(item.getItemsId()))
                .map(EditDesignerProjectListingItemsDTO::getItemsId)
                .collect(Collectors.toList());
        BizAssert.isTrue(filter.size() == filter.stream().distinct().count(), ResultCode.VERIFY.build(45), "ItemsId存在重复数据");
    }

    @Transactional
    public List<DesignerProjectListingItemsDTO> updateListingItems(DesignerProject project, List<EditDesignerProjectListingItemsDTO> editList, String updateUser) {
        // 检查参数
        verifyListing(editList);
        IntStream.range(0, editList.size()).forEachOrdered(i -> {
            EditDesignerProjectListingItemsDTO edit = editList.get(i);
            if (edit.getChangeType() == 1) {
                if (Check.isNull(edit.getItemsId())) {
                    // 添加
                    DesignerProjectItems items = create(project, edit, i, updateUser);
                    edit.setItemsId(items.getItemsId());
                } else {
                    // 修改
                    update(project, edit, i, updateUser);
                }
                // 变更内容
                designerProjectItemsProductManager.update(project, edit.getItemsId(), edit.getPickProducts(), updateUser);
            } else if (edit.getChangeType() == 2 && Check.notNull(edit.getItemsId())) {
                delete(project, edit.getItemsId(), updateUser);
                // 删除产品
                designerProjectItemsProductManager.deleteByItemsId(project, edit.getItemsId(), updateUser);
                // 删除自定义数据
                designerProjectItemsProductCustomManager.deleteByItemsId(project, edit.getItemsId(), updateUser);
                edit.setItemsId(null);
            }
        });
        return editList.stream().filter(item -> Check.notNull(item.getItemsId())).collect(Collectors.toList());
    }

    private DesignerProjectItems create(DesignerProject project, EditDesignerProjectListingItemsDTO edit, int sorting, String createUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setUserId(project.getUserId());
        record.setProjectId(project.getProjectId());
        record.setName(edit.getPositionDescr());
        record.setPositionDescr(edit.getPositionDescr());
        record.setSorting(sorting);
        record.setDeleted(NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);
        return record;
    }

    private void update(DesignerProject project, EditDesignerProjectListingItemsDTO edit, int sorting, String updateUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setName(edit.getPositionDescr());
        record.setPositionDescr(edit.getPositionDescr());
        record.setSorting(sorting);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        DesignerProjectItemsExample example = new DesignerProjectItemsExample();
        example.createCriteria()
                .andItemsIdEqualTo(edit.getItemsId())
                .andProjectIdEqualTo(project.getProjectId())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.name,
                Column.positionDescr,
                Column.sorting,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(40), "修改条目失败");
    }

    private void delete(DesignerProject project, Integer itemsId, String updateUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setDeleted(IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        DesignerProjectItemsExample example = new DesignerProjectItemsExample();
        example.createCriteria()
                .andItemsIdEqualTo(itemsId)
                .andProjectIdEqualTo(project.getProjectId())
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.deleted,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(40), "删除条目失败");
    }

    void deleteByProjectId(Integer projectId, String updateUser) {
        DesignerProjectItemsWithBLOBs record = new DesignerProjectItemsWithBLOBs();
        record.setDeleted(IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        DesignerProjectItemsExample example = new DesignerProjectItemsExample();
        example.createCriteria()
                .andProjectIdEqualTo(projectId)
                .andDeletedEqualTo(NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.deleted,
                Column.updateUser,
                Column.updateTime);
    }

    public List<DesignerProjectItemsWithBLOBs> queryByProjectId(Integer projectId) {
        DesignerProjectItemsExample example = new DesignerProjectItemsExample();
        example.createCriteria()
                .andProjectIdEqualTo(projectId)
                .andDeletedEqualTo(NOT_DELETED);
        example.orderBy(Column.sorting.asc());
        return dao.selectByExampleWithBLOBs(example);
    }
}